﻿/*
* 创建者：LIYINFAI
* 创建时间：2023/10/15 11:40:00
* 描述：
* --------------------------------------
* 修改说明：
* --------------------------------------
*/
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace CommonLibrary
{
    /// <summary>
    /// 设备没有数据返回，可视设备为非工作状态或异常
    /// </summary>
    public delegate void DeviceEmptyReturnNotifyDelegate(BaseHelper helper);
    /// <summary>
    /// 事件代理，显示信息
    /// </summary>
    /// <param name="message"></param>
    /// <param name="isOk"></param>
    public delegate void ShowMessageDelegate(string message, bool isOk);
    /// <summary>
    /// 事件代理，显示错误
    /// </summary>
    /// <param name="message"></param>
    public delegate void ShowErrorMessageDelegate(string message);
    /// <summary>
    /// 自定义自检代理
    /// </summary>
    public delegate void CustomSelfCheckHandlerDelegate();
    /// <summary>
    /// 自定义执行前操作
    /// </summary>
    public delegate void CustomSelfExecuteHandlerDelegate();
    /// <summary>
    /// 手动串口代理
    /// </summary>
    public delegate void ManualSerialHandlerDelegate();
    /// <summary>
    /// 仪器基础操作父类
    /// </summary>
    public class BaseHelper
    {
        /// <summary>
        /// 状态地址
        /// </summary>
        public string StatusAddress { get; set; } = string.Empty;
        /// <summary>
        /// 串口操作锁
        /// </summary>
        public readonly object COM_LOCK = new object();
        /// <summary>
        /// Tcp操作锁
        /// </summary>
        public readonly object TCP_LOCK = new object();
        /// <summary>
        /// Modbus操作锁
        /// </summary>
        public readonly object MODBUS_LOCK = new object();
        /// <summary>
        /// 获取返回数据时每次的休眠时间，默认5ms
        /// </summary>
        public readonly int DEQUEUE_SLEEP_TIMES = 5;
        /// <summary>
        /// 串口返回信息队列
        /// </summary>
        private Queue<byte[]> mSerialMessageQueue = new Queue<byte[]>();
        /// <summary>
        /// 自定义自检逻辑
        /// </summary>
        public CustomSelfCheckHandlerDelegate CustomSelfCheckHandler { get; set; } = null;
        /// <summary>
        /// 自定义执行前操作
        /// </summary>
        public CustomSelfExecuteHandlerDelegate CustomSelfExecuteHandler { get; set; } = null;
        /// <summary>
        /// 手动串口处理
        /// </summary>
        public ManualSerialHandlerDelegate ManualSerialHandler { get; set; } = null;
        /// <summary>
        /// 显示信息
        /// </summary>
        public ShowMessageDelegate ShowMessage { get; set; } = null;
        /// <summary>
        /// 显示错误信息
        /// </summary>
        public ShowErrorMessageDelegate ShowErrorMessage { get; set; } = null;
        /// <summary>
        /// 设备没有数据返回，可视设备为非工作状态或异常
        /// </summary>
        public DeviceEmptyReturnNotifyDelegate DeviceEmptyReturnNotify { get; set; } = null;
        #region
        /// <summary>
        /// 执行锁，保证每个设置当前处理命令为一个
        /// </summary>
        private object EXECUTE_LOCK = new object();
        /// <summary>
        /// 自检锁，保证数据完整性
        /// </summary>
        private object SELF_CHECK_LOCK = new object();
        /// <summary>
        /// 是否完成初始化
        /// </summary>
        public bool HasInit { get; set; } = false;
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; } = string.Empty;
        /// <summary>
        /// 触发器列表
        /// </summary>
        public List<TriggerHandler> TriggerHandlers { get; set; } = new List<TriggerHandler>();
        /// <summary>
        /// 任务执行间隔，默认50毫秒
        /// </summary>
        public int RunInterval { get; set; } = 150;
        /// <summary>
        /// 通讯类型，默认TCP
        /// </summary>
        public ECommunicationType CommunicationType { get; set; } = ECommunicationType.TCP;
        /// <summary>
        /// 通讯超时时间，默认1000毫秒
        /// </summary>
        public virtual int CommunicationTimeout => 1000;
        private Thread mSerialPortReadThread = null;
        private bool mSerialPortReading = false;
        /// <summary>
        /// 自动串口相关信息
        /// </summary>
        public SerialEntity SerialEntityData { get; set; } = null;
        /// <summary>
        /// TCP相关信息
        /// </summary>
        public TcpEntity TcpEntityData { get; set; } = null;
        /// <summary>
        /// Modbus相关信息
        /// </summary>
        public ModbusEntity ModbusEntityData { get; set; } = null;
        /// <summary>
        /// 自动串口对象
        /// </summary>
        private SerialPort SerialPortEntity { get; set; } = null;
        /// <summary>
        /// Socket对象
        /// </summary>
        private Socket SocketEntity { get; set; } = null;
        private bool mNeedSelfCheck = false;
        /// <summary>
        /// 构造函数
        /// </summary>
        public BaseHelper()
        {
            StartSelfCheck();
        }
        private static object LOCK_TRIGGER_LIST = new object();
        private static object LOCK_TRIGGER_VALUES = new object();
        private static List<PLCTagSetting> TRIGGER_LIST = new List<PLCTagSetting>();
        private static Dictionary<string, object> TRIGGER_VALUES = new Dictionary<string, object>();
        /// <summary>
        /// 
        /// </summary>
        /// <param name="triggerHandler"></param>
        public static void AddTriggerHanlder(TriggerHandler triggerHandler)
        {
            lock (LOCK_TRIGGER_LIST)
            {
                if (triggerHandler != null && !string.IsNullOrWhiteSpace(triggerHandler.TriggerAddress))
                {
                    TRIGGER_LIST.Add(new PLCTagSetting()
                    {
                        ORMName = triggerHandler.TriggerAddress,
                        TypeName = triggerHandler.TriggerDataType.ToString().ToLower(),
                        Tag = triggerHandler.TriggerAddress
                    });
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        public static void ClearTriggerHandler()
        {
            lock (LOCK_TRIGGER_LIST)
            {
                TRIGGER_LIST.Clear();
            }
        }
        private static object GetTriggerValue(string plcAddress)
        {
            if (GlobalStatus.APP == EAppStatus.RUN)
            {
                lock (LOCK_TRIGGER_VALUES)
                {
                    object value = null;
                    if (!string.IsNullOrWhiteSpace(plcAddress) && TRIGGER_VALUES != null && TRIGGER_VALUES.Count > 0 && TRIGGER_VALUES.ContainsKey(plcAddress))
                    {
                        value = TRIGGER_VALUES[plcAddress];
                    }
                    return value;
                }
            }
            else
            {
                return null;
            }
        }
        private static void GetAllTriggerValues()
        {
            lock (LOCK_TRIGGER_VALUES)
            {
#if DEBUG
                LogHelper.Debug($"【BaseHelper】BatchRead - 1 {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}\r\n{CommonHelper.GetJsonString(TRIGGER_VALUES)}");
#endif
                TRIGGER_VALUES = APPInstance.PLC.BatchRead(TRIGGER_LIST);

#if DEBUG
                LogHelper.Debug($"【BaseHelper】BatchRead - 2 {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}\r\n{CommonHelper.GetJsonString(TRIGGER_VALUES)}");
#endif
                if (TRIGGER_VALUES != null && TRIGGER_VALUES.Count > 0)
                {
                    var keys = TRIGGER_VALUES.Keys.ToList();
                    foreach (var t in keys)
                    {
                        if (IsDisable(t))
                        {
                            TRIGGER_VALUES[t] = null;
                        }
                    }
#if DEBUG
                    foreach (var k in keys)
                    {
                        if (TRIGGER_VALUES[k] != null && TRIGGER_VALUES[k].Equals((short)1))
                        {
                            LogHelper.Debug($"【BaseHelper】【{k}】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
                        }
                    }
#endif
                }
            }
        }
        private static List<string> DISABLE_TRIGGERS = new List<string>();
        private static object LOCK_DISABLE = new object();
        private static bool IsDisable(string triggerAddress)
        {
            lock (LOCK_DISABLE)
            {
                return string.IsNullOrWhiteSpace(triggerAddress) ? false : DISABLE_TRIGGERS.Contains(triggerAddress);
            }
        }
        private static void SetDisable(string triggerAddress)
        {
            if (GlobalStatus.APP == EAppStatus.RUN)
            {
                lock (LOCK_DISABLE)
                {
                    if (!string.IsNullOrWhiteSpace(triggerAddress) && !DISABLE_TRIGGERS.Contains(triggerAddress))
                    {
                        DISABLE_TRIGGERS.Add(triggerAddress);
                    }
                }
            }
        }
        private static void ClearDisable(string triggerAddress)
        {
            if (GlobalStatus.APP == EAppStatus.RUN)
            {
                lock (LOCK_DISABLE)
                {
                    if (!string.IsNullOrWhiteSpace(triggerAddress) && DISABLE_TRIGGERS.Contains(triggerAddress))
                    {
                        DISABLE_TRIGGERS.Remove(triggerAddress);
                    }
                }
            }
        }
        /// <summary>
        /// 启动触发器的值的读取
        /// </summary>
        public static void StartReadTriggers()
        {
            lock (LOCK_DISABLE)
            {
                DISABLE_TRIGGERS.Clear();
            }
            new Thread(() =>
            {
                while (GlobalStatus.APP == EAppStatus.RUN)
                {
                    GetAllTriggerValues();
                    Thread.Sleep(100);
                }
            })
            { IsBackground = true }.Start();
        }
        /// <summary>
        /// 是否连接
        /// </summary>
        public bool IsConnected
        {
            get
            {
                bool result = false;
                try
                {
                    bool validSerial = false, validTcp = false;
                    if (this.SerialPortEntity != null && this.SerialPortEntity.IsOpen)
                    {
                        validSerial = true;
                    }
                    if (this.SocketEntity != null && this.SocketEntity.Connected)
                    {
                        validTcp = true;
                    }
                    result = validSerial || validTcp;
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex, $"【{this.Name}】");
                }
                return result;
            }
        }


        private object READ_LOCK = new object();
        /// <summary>
        /// 通过串口执行命令
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public string RunComCommand(string command)
        {
            lock (READ_LOCK)
            {
                string result = string.Empty;
                if (this.IsConnected)
                {
                    try
                    {
                        this.SerialSendString(command);
                        result = this.GetSerialReturnUTF8String();
                    }
                    catch (Exception ex)
                    {
                        string tag = this.SerialEntityData != null ? $"【{this.Name}】【{this.SerialEntityData.PortName}】" : "";
                        LogHelper.Error(ex, tag);
                    }
                }
                return result;
            }
        }
        /// <summary>
        /// 通过TCP执行命令
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public string RunTcpCommand(string command)
        {
            lock (READ_LOCK)
            {
                string result = string.Empty;
                if (this.IsConnected)
                {
                    try
                    {
                        this.TcpSend(Encoding.UTF8.GetBytes(command));
                        result = this.TcpReceiveString();
                    }
                    catch (Exception ex)
                    {
                        string tag = this.TcpEntityData != null ? $"【{this.Name}】【{this.TcpEntityData.IP}:{this.TcpEntityData.Port}】" : "";
                        LogHelper.Error(ex, tag);
                    }
                }
                return result;
            }
        }
        /// <summary>
        /// 标题
        /// </summary>
        public string Title =>
            this.CommunicationType == ECommunicationType.TCP && this.TcpEntityData != null ? $"{this.TcpEntityData.IP}:{this.TcpEntityData.Port}" :
                (this.CommunicationType == ECommunicationType.SERIAL && this.SerialEntityData != null ? this.SerialEntityData.PortName :
            (this.CommunicationType == ECommunicationType.MANUAL_SERIAL && this.SerialEntityData != null) ? this.SerialEntityData.PortName : "");
        /// <summary>
        /// TCP方式发送
        /// </summary>
        /// <param name="cmd"></param>
        public bool TcpSend(byte[] cmd)
        {
            lock (this.TCP_LOCK)
            {
                bool success = false;
                if (this.SocketEntity != null)
                {
                    CommonHelper.ClearSocketCache(this.SocketEntity);
                    LogHelper.Info($"【{this.Name}】开始发送数据：【{(string.Join(" ", cmd.Select(v => v.ToString("X2"))))}】");
                    var num = this.SocketEntity.Send(cmd);
                    success = num == cmd.Length;
                    LogHelper.Info($"【{this.Name}】结束发送数据：【{(string.Join(" ", cmd.Select(v => v.ToString("X2"))))}】");
                }
                return success;
            }
        }
        /// <summary>
        /// 不提倡用，一般使用手动的情况可以考虑用
        /// </summary>
        /// <returns></returns>
        public byte[] SerialRead()
        {
            lock (this.COM_LOCK)
            {
                byte[] result = null;
                int len = this.SerialPortEntity.BytesToRead;
                if (len > 0)
                {
                    result = new byte[len];
                    this.SerialPortEntity.Read(result, 0, len);
                }
                return result;
            }
        }
        /// <summary>
        /// 串口发送（ASCII编码字符串）
        /// </summary>
        /// <param name="cmd"></param>
        public void SerialSendASCIIString(byte[] cmd)
        {
            SerialSendString(Encoding.ASCII.GetString(cmd));
        }
        /// <summary>
        /// 串口发送
        /// </summary>
        /// <param name="cmd"></param>
        public void SerialSendString(string cmd)
        {
            lock (this.COM_LOCK)
            {
                if (!string.IsNullOrWhiteSpace(cmd))
                {
                    this.ClearSerial();
                    LogHelper.Info($"【{this.Name}】开始发送数据：【{cmd.Replace("\n", "\\n").Replace("\r", "\\r")}】");
                    this.SerialPortEntity.Write(cmd);
                    LogHelper.Info($"【{this.Name}】结束发送数据：【{cmd.Replace("\n", "\\n").Replace("\r", "\\r")}】");
                }
            }
        }
        /// <summary>
        /// 串口发送
        /// </summary>
        /// <param name="cmd"></param>
        public void SerialSend(byte[] cmd)
        {
            lock (this.COM_LOCK)
            {
                if (cmd != null && cmd.Length > 0)
                {
                    this.ClearSerial();
                    LogHelper.Info($"【{this.Name}】开始发送数据：【{string.Join(" ", cmd.Select(v => v.ToString("X2")))}】");
                    this.SerialPortEntity.Write(cmd, 0, cmd.Length);
                    LogHelper.Info($"【{this.Name}】结束发送数据：【{string.Join(" ", cmd.Select(v => v.ToString("X2")))}】");
                }
            }
        }
        /// <summary>
        /// TCP接收
        /// </summary>
        /// <returns></returns>
        public byte[] TcpReceive()
        {
            lock (this.TCP_LOCK)
            {
                List<byte> data = new List<byte>();
                try
                {
                    if (this.SocketEntity != null)
                    {
                        byte[] buffer = new byte[1024];
                        this.SocketEntity.ReceiveTimeout = this.CommunicationTimeout;
                        int length = this.SocketEntity.Receive(buffer);
                        while (length > 0)
                        {
                            data.AddRange(buffer.Take(length));
                            if (length < 1024)
                            {
                                break;
                            }
                            buffer = new byte[1024];
                            length = this.SocketEntity.Receive(buffer);
                        }
                        if (data.Count > 0 && this.TcpEntityData != null)
                        {
                            LogHelper.Info($"【{this.Name}】 TCP {this.TcpEntityData.IP}:{this.TcpEntityData.Port} 有数据响应：{string.Join(" ", data.Select(v => v.ToString("X2")))}");
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (ex is SocketException)
                    {
                        var socketEx = ex as SocketException;
                        this.RealShowErrorMessage($"{(this.SocketEntity != null ? $"【IP:{this.SocketEntity.RemoteEndPoint}】 " : "")}仪器/设备未开机或未上电", socketEx.Message);
                    }
                    else
                    {
                        this.RealShowErrorMessage(ex, $"{(this.SocketEntity != null ? $"【IP:{this.SocketEntity.RemoteEndPoint}】 " : "")}");
                    }
                }
                return data.ToArray();
            }
        }
        /// <summary>
        /// TCP接收
        /// </summary>
        /// <returns></returns>
        public string TcpReceiveString()
        {
            string result = "";
            try
            {
                byte[] buffer = TcpReceive();
                if (buffer != null && buffer.Length > 0)
                {
                    result = Encoding.UTF8.GetString(buffer);
                }
            }
            catch (Exception ex)
            {
                if (ex is SocketException)
                {
                    var socketEx = ex as SocketException;
                    this.RealShowErrorMessage($"{(this.SocketEntity != null ? $"【IP:{this.SocketEntity.RemoteEndPoint}】 " : "")}仪器/设备未开机或未上电", socketEx.Message);
                }
                else
                {
                    this.RealShowErrorMessage(ex, $"{(this.SocketEntity != null ? $"【IP:{this.SocketEntity.RemoteEndPoint}】 " : "")}");
                }
            }
            return result;
        }
        /// <summary>
        /// 获取队列数据
        /// </summary>
        /// <param name="needCheck"></param>
        /// <param name="startByte"></param>
        /// <param name="endByte"></param>
        /// <returns></returns>
        public byte[] GetReturnBuffer(bool needCheck = false, byte startByte = 0x00, byte endByte = 0x00)
        {
            lock (this.COM_LOCK)
            {
                List<byte> list = new List<byte>();
                byte[] result = null;
                int sleepTimes = 0;
                LogHelper.Info($"【{this.Name}】 超时时间：{this.CommunicationTimeout}");
                while (sleepTimes < this.CommunicationTimeout)
                {
                    while (this.mSerialMessageQueue.Count > 0)
                    {
                        byte[] serialReceivedData = this.mSerialMessageQueue.Dequeue();
                        result = serialReceivedData == null || serialReceivedData.Length == 0 ? null : serialReceivedData;
                        if (result != null && result.Length > 0)
                        {
                            list.AddRange(result);
                        }
                        sleepTimes = 0;
                    }
                    if (needCheck && list.Count > 0 && list[0] == startByte && list[list.Count - 1] == endByte)
                    {
                        break;
                    }
                    else if (!needCheck && list.Count > 0)
                    {
                        break;
                    }
                    Thread.Sleep(DEQUEUE_SLEEP_TIMES);
                    sleepTimes += DEQUEUE_SLEEP_TIMES;
                }

                if (list.Count > 0 && this.SerialEntityData != null)
                {
                    LogHelper.Info($"【{this.Name}】 COM {this.SerialEntityData.PortName} 有数据响应：{string.Join(" ", list.Select(v => v.ToString("X2")))}");
                }
                return list.Count == 0 ? null : list.ToArray();
            }
        }
        /// <summary>
        /// 获取队列数据（UTF8)
        /// </summary>
        /// <returns></returns>
        public string GetSerialReturnUTF8String()
        {
            byte[] buffer = GetReturnBuffer();
            return CommonHelper.RemoveEnterString(buffer == null || buffer.Length == 0 ? "" : Encoding.UTF8.GetString(buffer));
        }
        /// <summary>
        /// 获取队列数据（ASCII)
        /// </summary>
        /// <returns></returns>
        public string GetSerialReturnASCIIString()
        {
            byte[] buffer = GetReturnBuffer();
            return CommonHelper.RemoveEnterString(buffer == null || buffer.Length == 0 ? "" : Encoding.ASCII.GetString(buffer));
        }
        /// <summary>
        /// 重置触发器值
        /// </summary>
        private void ResetTrigger(string triggerAddress, EDataType triggerDataType, object resetTriggerValue)
        {
            if (GlobalStatus.APP == EAppStatus.RUN && APPInstance.PLC != null && APPInstance.PLC.IsConnected)
            {
                switch (triggerDataType)
                {
                    case EDataType.SHORT:
                        var shortValue = (short)resetTriggerValue;
                        APPInstance.PLC.Write(triggerAddress, shortValue);
                        break;
                    case EDataType.INT:
                        var intValue = (int)resetTriggerValue;
                        APPInstance.PLC.Write(triggerAddress, intValue);
                        break;
                    case EDataType.BOOL:
                        var boolValue = (bool)resetTriggerValue;
                        APPInstance.PLC.Write(triggerAddress, boolValue);
                        break;
                    case EDataType.USHORT:
                        var ushortValue = (ushort)resetTriggerValue;
                        APPInstance.PLC.Write(triggerAddress, ushortValue);
                        break;
                    case EDataType.UINT:
                        var uintValue = (uint)resetTriggerValue;
                        APPInstance.PLC.Write(triggerAddress, uintValue);
                        break;
                    case EDataType.FLOAT:
                        var floatValue = (float)resetTriggerValue;
                        APPInstance.PLC.Write(triggerAddress, floatValue);
                        break;
                }
            }
        }
        /// <summary>
        /// 是否触发任务
        /// </summary>
        /// <returns></returns>
        private bool IsEqualTrigger(string triggerAddress, EDataType triggerDataType, object triggerValue)
        {
            bool result = false;
            if (APPInstance.PLC != null && APPInstance.PLC.IsConnected)
            {
                switch (triggerDataType)
                {
                    case EDataType.SHORT:
                        var shortTarget = (short)triggerValue;
                        var shortValue = APPInstance.PLC.ReadShort(triggerAddress);
                        result = shortTarget == shortValue;
                        break;
                    case EDataType.INT:
                        var intTarget = (int)triggerValue;
                        var intValue = APPInstance.PLC.ReadInt(triggerAddress);
                        result = intTarget == intValue; break;
                    case EDataType.BOOL:
                        var boolTarget = (bool)triggerValue;
                        var boolValue = APPInstance.PLC.ReadBool(triggerAddress);
                        result = boolTarget == boolValue; break;
                    case EDataType.USHORT:
                        var ushortTarget = (ushort)triggerValue;
                        var ushortValue = APPInstance.PLC.ReadUShort(triggerAddress);
                        result = ushortTarget == ushortValue;
                        break;
                    case EDataType.UINT:
                        var uintTarget = (uint)triggerValue;
                        var uintValue = APPInstance.PLC.ReadUInt(triggerAddress);
                        result = uintTarget == uintValue; break;
                    case EDataType.FLOAT:
                        var floatTarget = (float)triggerValue;
                        var floatValue = APPInstance.PLC.ReadFloat(triggerAddress);
                        result = floatTarget == floatValue; break;
                }
            }
            return result;
        }
        /// <summary>
        /// 关闭通讯
        /// </summary>
        private void CloseCommunication()
        {
            if (this.SerialPortEntity != null && this.SerialPortEntity.IsOpen)
            {
                try
                {
                    this.SerialPortEntity.Close();
                    this.SerialPortEntity = null;
                }
                catch (Exception ex)
                {
                    string tag = this.SerialEntityData != null ? $"【{this.Name}】【{this.SerialEntityData.PortName}】" : "";
                    this.RealShowErrorMessage(ex, tag);
                }
            }
            if (this.SocketEntity != null && this.SocketEntity.Connected)
            {
                try
                {
                    this.SocketEntity.Close();
                    this.SocketEntity = null;
                }
                catch (Exception ex)
                {
                    string tag = this.TcpEntityData != null ? $"【{this.Name}】【{this.TcpEntityData.IP}:{this.TcpEntityData.Port}】" : "";
                    this.RealShowErrorMessage(ex, tag);
                }
            }
        }
        /// <summary>
        /// 清理串口缓存
        /// </summary>
        public void ClearSerial()
        {
            if (this.SerialPortEntity != null && this.SerialPortEntity.IsOpen)
            {
                this.SerialPortEntity.DiscardInBuffer();
                this.SerialPortEntity.DiscardOutBuffer();
            }
            this.mSerialMessageQueue.Clear();
        }
        /// <summary>
        /// 消息显示
        /// </summary>
        /// <param name="message"></param>
        /// <param name="isOk"></param>
        public void RealShowMessage(string message, bool isOk = true)
        {
            LogHelper.Info(message);
            if (this.ShowMessage != null)
            {
                this.ShowMessage(message, isOk);
            }
        }
        /// <summary>
        /// 错误消息显示
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="tag"></param>
        public void RealShowErrorMessage(Exception ex, string tag = "")
        {
            LogHelper.Error(ex, tag);
            if (this.ShowErrorMessage != null)
            {
                this.ShowErrorMessage($"【{this.Name}】 {tag}{ex.Message},{ex.StackTrace}");
            }
        }
        /// <summary>
        /// 错误消息显示
        /// </summary>
        /// <param name="message"></param>
        /// <param name="tag"></param>
        public void RealShowErrorMessage(string message, string tag = "")
        {
            LogHelper.Error(null, this.Name, $"{message} {tag}");
            if (this.ShowErrorMessage != null)
            {
                this.ShowErrorMessage($"【{this.Name}】 {message}");
            }
        }
        /// <summary>
        /// 初始化通讯
        /// </summary>
        private void InitCommunication()
        {
            lock (this.SELF_CHECK_LOCK)
            {
                if (this.CommunicationType.Equals(ECommunicationType.SERIAL) &&
                    ((this.SerialPortEntity == null && this.SerialEntityData != null)
                    || (this.SerialPortEntity != null && !this.SerialPortEntity.IsOpen && this.SerialEntityData != null))
                    )
                {
                    lock (this.COM_LOCK)
                    {
                        this.SerialPortEntity = new SerialPort(
                            this.SerialEntityData.PortName,
                            this.SerialEntityData.BaudRate,
                            CommonHelper.GetEnumByRealValue<Parity>(this.SerialEntityData.ParityBit, Parity.None),
                            this.SerialEntityData.DataBit,
                            CommonHelper.GetEnumByRealValue<StopBits>(this.SerialEntityData.StopBit, StopBits.One)
                            );
                        this.SerialPortEntity.WriteTimeout = this.CommunicationTimeout;
                        this.SerialPortEntity.ReadTimeout = this.CommunicationTimeout;
                        this.SerialPortEntity.DtrEnable = true;
                        this.SerialPortEntity.RtsEnable = true;
                        try
                        {
                            if (this.mSerialPortReadThread != null && this.mSerialPortReadThread.ThreadState == System.Threading.ThreadState.Running)
                            {
                                this.mSerialPortReading = false;
                                this.mSerialPortReadThread.Join();
                                this.mSerialPortReadThread = null;
                            }
                            this.mSerialPortReading = true;
                            this.mSerialPortReadThread = new Thread(AutoSerialDataReceivedThread);
                            this.SerialPortEntity.Open();
                            this.mSerialPortReadThread.Start();
                            ClearSerial();
                            LogHelper.Info($"{this.Name} 串口初始化");
                        }
                        catch (Exception ex)
                        {
                            string tag = this.SerialEntityData != null ? $"【{this.Name}】【{this.SerialEntityData.PortName}】" : "";
                            this.SerialPortEntity = null;
                            this.RealShowErrorMessage(ex, tag);
                        }
                    }
                }
                else if (this.CommunicationType.Equals(ECommunicationType.TCP) &&
                    ((this.SocketEntity == null && this.TcpEntityData != null)
                    || (this.SocketEntity != null && !this.SocketEntity.Connected && this.TcpEntityData != null))
                    )
                {
                    lock (this.TCP_LOCK)
                    {
                        this.SocketEntity = new Socket(AddressFamily.InterNetwork,
                        SocketType.Stream, ProtocolType.Tcp);
                        this.SocketEntity.SendTimeout = this.CommunicationTimeout;
                        this.SocketEntity.ReceiveTimeout = this.CommunicationTimeout;
                        try
                        {
                            var asyncResult = this.SocketEntity.BeginConnect(this.TcpEntityData.IP, this.TcpEntityData.Port, null, null);
                            bool success = asyncResult.AsyncWaitHandle.WaitOne(500, true);
                            if (this.SocketEntity != null && this.SocketEntity.Connected)
                            {
                                this.SocketEntity.EndConnect(asyncResult);
                                LogHelper.Info($"{this.Name} TCP初始化成功");
                                Console.WriteLine($"【{this.Name}】 成功{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
                            }
                            else
                            {
                                this.SocketEntity = null;
                                this.RealShowErrorMessage(new ArgumentException($"{this.Name} TCP初始化失败"));
                                Console.WriteLine($"【{this.Name}】 失败{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
                            }
                        }
                        catch (Exception ex)
                        {
                            string tag = this.TcpEntityData != null ? $"【{this.Name}】【{this.TcpEntityData.IP}:{this.TcpEntityData.Port}】" : "";
                            this.SocketEntity = null;
                            this.RealShowErrorMessage(ex, tag);
                        }
                    }
                }
                else
                if (this.CommunicationType.Equals(ECommunicationType.MANUAL_SERIAL) &&
                    ((this.SerialPortEntity == null && this.SerialEntityData != null)
                    || (this.SerialPortEntity != null && !this.SerialPortEntity.IsOpen && this.SerialEntityData != null))
                    )
                {
                    lock (this.COM_LOCK)
                    {
                        this.SerialPortEntity = new SerialPort(
                        this.SerialEntityData.PortName,
                        this.SerialEntityData.BaudRate,
                        CommonHelper.GetEnumByRealValue<Parity>(this.SerialEntityData.ParityBit, Parity.None),
                        this.SerialEntityData.DataBit,
                        CommonHelper.GetEnumByRealValue<StopBits>(this.SerialEntityData.StopBit, StopBits.One)
                        );

                        this.SerialPortEntity.DataReceived += ManualSerialDataReceived;
                        this.SerialPortEntity.WriteTimeout = this.CommunicationTimeout;
                        this.SerialPortEntity.ReadTimeout = this.CommunicationTimeout;
                        this.SerialPortEntity.DtrEnable = true;
                        this.SerialPortEntity.RtsEnable = true;
                        try
                        {
                            this.SerialPortEntity.Open();
                            ClearSerial();
                            LogHelper.Info($"{this.Name} 手动串口初始化");
                        }
                        catch (Exception ex)
                        {
                            string tag = this.SerialEntityData != null ? $"【{this.Name}】【{this.SerialEntityData.PortName}】" : "";
                            this.SerialPortEntity = null;
                            this.RealShowErrorMessage(ex, tag);
                        }
                    }
                }
                this.HasInit = true;
            }
        }
        private void AutoSerialDataReceivedThread()
        {
            while (this.mSerialPortReading)
            {
                try
                {
                    //CommonHelper.ApplicationEvents();

                    int length = this.SerialPortEntity != null && this.SerialPortEntity.IsOpen ? this.SerialPortEntity.BytesToRead : 0;
                    if (length > 0)
                    {
                        byte[] serialReceivedData = new byte[length];
                        this.SerialPortEntity.Read(serialReceivedData, 0, length);
                        this.mSerialMessageQueue.Enqueue(serialReceivedData);
                    }
                    Thread.Sleep(50);
                }
                catch (Exception ex)
                {
                    string tag = this.SerialEntityData != null ? $"【{this.Name}】【{this.SerialEntityData.PortName}】" : "";
                    this.RealShowErrorMessage(ex, tag);
                }
            }
        }
        private void ManualSerialDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            LogHelper.Info($"【{this.Name}】 串口 {this.SerialEntityData.PortName} 有数据响应");
            ManualSerialHandler();
        }
        /// <summary>
        /// 自测
        /// </summary>
        public void StartSelfCheck()
        {
            this.mNeedSelfCheck = true;
            this.mSerialPortReading = this.CommunicationType == ECommunicationType.SERIAL;
            new Thread(() =>
            {
                while (this.mNeedSelfCheck)
                {
                    InitCommunication();
                    if (this.CustomSelfCheckHandler != null)
                    {
                        this.CustomSelfCheckHandler();
                    }
                    Thread.Sleep(1000);
                }
            }).Start();
        }
        /// <summary>
        /// 执行任务
        /// </summary>
        private void Execute()
        {
            if (this.TriggerHandlers != null && this.TriggerHandlers.Count > 0)
            {
                foreach (var tHandler in this.TriggerHandlers)
                {
                    new Thread(() =>
                    {
                        while (GlobalStatus.APP == EAppStatus.RUN)
                        {
#if DEBUG
                            LogHelper.Debug($"【{this.Name}】BaseHelper Execute: 0 - {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
#endif
                            lock (this.EXECUTE_LOCK)
                            {
                                try
                                {
                                    var value = GetTriggerValue(tHandler.TriggerAddress);
                                    if (value != null && value.Equals(tHandler.TriggerValue))
                                    {
                                        SetDisable(tHandler.TriggerAddress);
                                        LogHelper.Info($"{tHandler.HandlerName}, 类型：{tHandler.HandlerType}, 地址：{tHandler.TriggerAddress}, 触发值：{tHandler.TriggerValue}");
                                        switch (this.CommunicationType)
                                        {
                                            case ECommunicationType.SERIAL: RealHandler(tHandler.HandlerName, tHandler.HandlerType, tHandler.OtherAddress, tHandler.OtherData); break;
                                            case ECommunicationType.TCP: RealHandler(tHandler.HandlerName, tHandler.HandlerType, tHandler.OtherAddress, tHandler.OtherData); break;
                                            case ECommunicationType.MODBUS_TCP: RealHandler(tHandler.HandlerName, tHandler.HandlerType, tHandler.OtherAddress, tHandler.OtherData); break;
                                        }
                                        ResetTrigger(tHandler.TriggerAddress, tHandler.TriggerDataType, tHandler.ResetValue);
                                        ClearDisable(tHandler.TriggerAddress);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    this.RealShowErrorMessage(ex);
                                }
                            }
#if DEBUG
                            LogHelper.Debug($"【{this.Name}】BaseHelper Execute: 1 - {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
#endif
                            Thread.Sleep(this.RunInterval);
                        }
                    }).Start();
                }
            }
        }
        /// <summary>
        /// 运行任务
        /// </summary>
        public void Run()
        {
            InitCommunication();
            if (this.CustomSelfExecuteHandler != null)
            {
                this.CustomSelfExecuteHandler();
            }
            Execute();
        }
        /// <summary>
        /// 启动
        /// </summary>
        public void Start()
        {
            this.ClearSerial();
            Thread thread =
            new Thread(() =>
            {
                Run();
            });
            thread.IsBackground = true;
            thread.Start();
            this.RealShowMessage($"{this.Name} 开启监控.");
        }
        /// <summary>
        /// 停止
        /// </summary>
        public void Stop()
        {
            this.RealShowMessage($"{this.Name} 停止监控.", false);
        }
        /// <summary>
        /// 退出
        /// </summary>
        public void Close()
        {
            this.mNeedSelfCheck = false;
            this.HasInit = false;
            this.mSerialPortReading = false;
            if (this.SerialPortEntity != null && this.SerialPortEntity.IsOpen)
            {
                try
                {
                    this.SerialPortEntity.Close();
                    this.SerialPortEntity = null;
                }
                catch (Exception ex)
                {
                    string tag = this.SerialEntityData != null ? $"【{this.SerialEntityData.PortName}】" : "";
                    this.RealShowErrorMessage(ex, tag);
                }
            }
            if (this.SocketEntity != null && this.SocketEntity.Connected)
            {
                try
                {
                    this.SocketEntity.Close();
                    this.SocketEntity = null;
                }
                catch (Exception ex)
                {
                    string tag = this.TcpEntityData != null ? $"【{this.TcpEntityData.IP}:{this.TcpEntityData.Port}】" : "";
                    this.RealShowErrorMessage(ex, tag);
                }
            }
            LogHelper.Info($"{this.Name} 退出.");
        }
        #endregion
        #region 子类需要实现的内容 
        /// <summary>
        /// 具体实现
        /// </summary>
        /// <param name="handlerName"></param>
        /// <param name="handlerType"></param>
        /// <param name="otherAddress"></param>
        /// <param name="otherData"></param>
        public virtual void RealHandler(string handlerName, EHandlerType handlerType, object otherAddress, object otherData)
        {
        }
        #endregion
    }
}
